<?php

namespace app\home\model;

use app\common\loader\ModelShop;
use app\common\loader\ModelVirtual;
use app\common\model\virtual\VirtualPromoModel as CommonVirtualPromoModel;
use think\Exception;
use think\facade\Cache;

/**
 * 虚码活动商品
 */
class VirtualPromoModel extends CommonVirtualPromoModel
{

    //
    private $keyMap = ['3' => 'sale_man', '2' => 'shop', '1' => 'shop_tag'];

    /**
     * 获取最优的活动信息
     * @param int $vpId 活动ID
     * @param int $userID 用户ID
     * @return array
     * @throws \think\db\exception\DataNotFoundException
     * @throws \think\db\exception\DbException
     * @throws \think\db\exception\ModelNotFoundException
     */
    public function getValidPromInfo(int $vpId, int $userID, array $promInfo = []): array
    {
        $result = [
            'id' => 0,                  // 活动ID
            'title' => '',              // 活动名称
            'small_ticket' => 0,        // 小票
            'red_packet' => 0,          // 红包
            'point' => 0,               // 积分
            'recheck_record' => 0,      // 审核
            'limit_num' => '',          // 总限制数
            'day_limit' => '',          // 日限制
            'union' => [],              // 联合规则   { sum: 0 ->保计满足数据,rule=2 有效, rule:-> 1: 商品满足 2,数量满足}
            'use_special' => false,     // 特殊规则  true 使用 ,false未使用
            'product_type' => 0,        // 活动类型
            'shop_id' => 0,             // 导购所在店铺
            'sales_man' => [],           // 导购信息
            'scanned_num' => 0,           // 已扫码数量
        ];

        if (empty($promInfo)) {
            $promInfo = $this->db()->where('id', $vpId)
                ->field('id,title,option,salesman,limit_num,union_rule,product_type,scanned_num')
                ->json(['option', 'salesman', 'union_rule'])
                ->where('status', 1)->find();
            if (empty($promInfo)) {
                throw  new Exception('活动ID无效', API_ERROR);
            }
        } else {
            if ($vpId !== $promInfo['id']) {
                $vpId = $promInfo['id'];
            }
        }

        // 获取 导购信息
        $userInfo = ModelShop::ShopSalesman()->getSalesManInfo($userID);
        if (empty($userInfo)) {
            throw  new Exception('导购信息无效', API_ERROR);
        }

        // 导购所在店铺
        $shopId = $userInfo['shop_id'];
        $shopIdInfo = ModelShop::Shop()->where(['id'=> $shopId, 'status' => 1])
            ->value(null,'id');
        if (empty($shopIdInfo)) {
            throw  new Exception('门店已被禁用,请联系客服', API_ERROR);
        }

        // 获取特殊规则
        $promSpecialInfo = $this->getPromoSpecialInfo($vpId);

        //组合数据
        $result['id'] = $promInfo['id'];
        $result['title'] = $promInfo['title'];
        $result['small_ticket'] = (int)($promInfo['option']['small_ticket'] ?? 0);
        $result['recheck_record'] = (int)($promInfo['option']['recheck_record'] ?? 0);
        $result['red_packet'] = (float)($promInfo['salesman']['red_packet'] ?? 0);
        $result['point'] = (int)($promInfo['salesman']['point'] ?? 0);
        $result['limit_num'] = (int)($promInfo['limit_num'] ?? 0);
        $result['day_limit'] = (int)($promInfo['salesman']['day_num'] ?? 0);
        $result['union'] = $promInfo['union_rule'] ?? [];
        $result['product_type'] = $promInfo['product_type'];
        $result['scanned_num'] = $promInfo['scanned_num'];
        $result['shop_id'] = $shopId;
        $result['sale_man'] = $userInfo;

        // 判断是否导购
        $tmpInfo = &$promSpecialInfo['sale_man'];
        if (!empty($tmpInfo) && isset($tmpInfo[$userID])) {
            $result['use_special'] = true;
            $result['small_ticket'] = (int)($tmpInfo[$userID]['small_ticket'] ?? $result['small_ticket']);
            $result['red_packet'] = (float)($tmpInfo[$userID]['red_packet'] ?? $result['red_packet']);
            $result['point'] = (int)($tmpInfo[$userID]['point'] ?? $result['point']);
        }

        // 处理店铺
        $tmpInfo = &$promSpecialInfo['shop'];
        if (!empty($tmpInfo) && isset($tmpInfo[$shopId]) && $result['use_special'] === false) {
            $result['use_special'] = true;
            $result['small_ticket'] = (int)($tmpInfo[$shopId]['small_ticket'] ?? $result['small_ticket']);
            $result['red_packet'] = (float)($tmpInfo[$shopId]['red_packet'] ?? $result['red_packet']);
            $result['point'] = (int)($tmpInfo[$shopId]['point'] ?? $result['point']);
        }

        // 处理店铺标签
        $tmpInfo = &$promSpecialInfo['shop_tag'];
        if (!empty($tmpInfo) && $result['use_special'] === false) {

            foreach ($tmpInfo as $info) {
                if (in_array((string)$shopId, $info['shop_ids'], true)) {
                    $result['use_special'] = true;
                    $result['small_ticket'] = (int)($info['small_ticket'] ?? $result['small_ticket']);
                    $result['red_packet'] = (float)($info['red_packet'] ?? $result['red_packet']);
                    $result['point'] = (int)($info['point'] ?? $result['point']);
                    break;
                }
            }
        }
        return $result;
    }


    /**
     * 拆分特殊规则
     * @param int $vpId 活动ID
     * @return array      ['shop_tag'=>'标签','shop'=>'店铺','sale_man'=>'导购']
     * @throws \think\db\exception\DataNotFoundException
     * @throws \think\db\exception\DbException
     * @throws \think\db\exception\ModelNotFoundException
     */
    public function getPromoSpecialInfo(int $vpId)
    {

        $result = [];
        $resultMap = [];
        $tagId = [];
        // 获取特殊规则
        $specialList = $this->db('virtual_promo_special')->json(['limit_way'])
            ->where('vp_id', $vpId)
            ->where('status', 1)
            ->field('type,limit_way,small_ticket,red_packet,point')
            ->order('type desc,sort desc,update_at desc,create_at desc')
            ->select();
        $temp = [];
        foreach ($specialList as $row) {
            if (empty($row['limit_way'])) {
                continue;
            }

            foreach ($row['limit_way'] as $item) {
                $temp[$item['id']] = [
                    'id' => $item['id'],
                    'title' => $item['title'],
                    'small_ticket' => $row['small_ticket'],
                    'red_packet' => $row['red_packet'],
                    'point' => $row['point']
                ];
                if ($row['type'] === 1) {
                    $tagId[] = $item['id'];
                }
            }
            $resultMap[$row['type']] = $temp;
        }
        // 补齐小特殊规则类型
        foreach ($this->keyMap as $k => $name) {
            $result[$name] = $resultMap[$k] ?? [];
        }
        // 店铺标识不为空,获取到对应标识 店铺ID
        if (!empty($tagId)) {
            $tagList = ModelShop::ShopTagsBind()->getShopIdForTagId($tagId);
            // 处理店铺标签
            foreach ($result['shop_tag'] as $id => &$v) {
                $v['shop_ids'] = explode(',', $tagList[$id] ?? '');
            }
        }
        return $result;
    }


    /**
     * 导购今天扫码的次数
     * @param string $mer_id 商户ID
     * @param int $vp_id 活动ID
     * @param int $user_id 导购ID
     * @param int $num 是否增加 >0 增加, =0 获取,,
     * @return int  返回次数
     */
    public function userScanNumForToday(string $mer_id, int $vp_id, int $user_id, int $num = 0): int
    {
        $cache_key = sprintf("%s_%d_%d_%s", $mer_id, $vp_id, $user_id, date('Y-m-d'));
        $result = Cache::get($cache_key, 0);
        if ($num > 0) {
            $result += $num;
            Cache::set($cache_key, $result, DAY_SECOND);
        }
        return $result;
    }


    /**
     * 提交保存虚码活动
     * @param string $mer_id |商户ID
     * @param int $vp_id |活动ID
     * @param int $user_id |导购ID
     * @param array $virtual_data |活动信息
     * @param array $product_list |商品列表
     * @param array $ticket |小票内容
     * @param string $order_no | 订单号
     * @return mixed
     * @throws Exception
     * @throws \JsonException
     * @throws \think\db\exception\DataNotFoundException
     * @throws \think\db\exception\DbException
     * @throws \think\db\exception\ModelNotFoundException
     */
    public function submitActivity(string $mer_id, int $vp_id, int $user_id, array $virtual_data, array $product_list, array $ticket , string $order_no)
    {

        /*$virtual_data = [
            'id' => 0,                  // 活动ID
            'title' => '',              // 活动名称
            'small_ticket' => 0,        // 小票
            'red_packet' => 0,          // 红包
            'point' => 0,               // 积分
            'recheck_record' => 0,      // 审核
            'limit_num' => '',          // 总限制数
            'day_limit' => '',          // 日限制
            'union' => [],              // 联合规则   { sum: 0 ->保计满足数据,rule=2 有效, rule:-> 1: 商品满足 2,数量满足}
            'use_special' => false,     // 特殊规则  true 使用 ,false未使用
            'product_type' => 0,        // 活动类型
            'shop_id' => 0,             // 导购所在店铺
            'sale_man' => [],           // 导购信息
            'scanned_num' => 0,           // 已扫码数量
        ];*/

        // 1. 更新导购积分
        // 2. 更新导购红包
        // 3. 增加扫码次
        // 4. 减少店铺库存
        // 5. 插入挚扫码日志

        try {
            $this->startTrans();

            //更新店铺库存
            ModelShop::ShopStock()->updateShopStock($mer_id, $virtual_data['shop_id'], $product_list);

            //更新活动已扫码数
            $this->updateStockMarket($vp_id, 1);

            $shop_info = ModelShop::Shop()->getShopTitle($virtual_data['shop_id'], 'title,op_user') ?? [];
            //添加虚码使用记录表

            $insertData = [
                'mer_id' => $mer_id,
                'vp_id' => $vp_id,
                'shop_id' => $virtual_data['shop_id'],
                'salesman_id' => $user_id,
                'red_packet' => $virtual_data['red_packet'],
                'point' => $virtual_data['point'],
                'status' => $virtual_data['recheck_record'] ? 0 : 1,
                'ticket_url' => implode(',', $ticket),
                'vp_title' => $virtual_data['title'],
                'shop_title' => $shop_info['title'],
                'product' => json_encode($product_list, JSON_UNESCAPED_UNICODE | JSON_THROW_ON_ERROR),
                // 管理员ID
                'admin_id' => $shop_info['op_user']
            ];

            // 不需要支付红包，默认为已完成
            if ((float)$virtual_data['red_packet'] === 0.0) {
                $insertData['status'] = 8;
            }

            $log_id = ModelVirtual::VirtualUsedLog()->insertGetId($insertData);

            //无需审核活动直接发放红包积分
            if ($virtual_data['recheck_record'] !== 1) {
                ModelVirtual::VirtualUsedLog()->sendPointAndRedPacket($mer_id, $user_id, $virtual_data['point'], $virtual_data['red_packet'], $log_id);
            }


            $this->commit();
            // 更新 导购的日扫码数 的缓存
            $this->userScanNumForToday($mer_id, $vp_id, $user_id, 1);
            ModelVirtual::VirtualScanTempLog()->where(['mer_id' => $mer_id, 'user_id' => $user_id ,'order_no' => $order_no])
                ->delete();
            return $log_id;
        } catch (Exception $e) {
            $this->rollback();
            throw  $e;
        }
    }

}
